home *** CD-ROM | disk | FTP | other *** search
-
-
- /* score_c.h - Definitions for classes related to the "score" program
- written for the Byte C++ Review
-
- May 1987 Mark E. Mallett
-
- */
-
- #ifndef NULL
- #define NULL (char *)0
- #endif
-
- /* This header file declares the following classes: */
- class SCORE_ITEM;
- class REST; // Derived from SCORE_ITEM
- class NOTE; // Derived from SCORE_ITEM
- class CHORD; // Derived from SCORE_ITEM
-
- class SEQUENCE; // Relates to SCORE_ITEM
- class SEQ_ITER; // Allows following a SEQUENCE
-
- enum NOTEVAL { C, Csh, D, Dsh, E, F, Fsh, G, Gsh, A, Ash, B };
- istream& operator>> ( istream&, NOTEVAL& );
-
- class SCORE_ITEM // Base class for all score items
- {
- int duration; // How long this item persists
- SCORE_ITEM* next; // Next SCORE_ITEM in the sequence
- friend class SEQUENCE;
- friend class SEQ_ITER;
- friend istream& operator>> ( istream&, SCORE_ITEM& );
- public:
- SCORE_ITEM( int d = 3 ){ duration = d; }
- ~SCORE_ITEM(){}
-
- int dur() { return duration; } // Retrieves duration value
- virtual void play(); // Plays a score item
- };
-
-
- class REST : public SCORE_ITEM // Musical rest-- marks a place
- {
- public:
- REST( int d = 3 ) : ( d ) {}
-
- void play();
- };
-
-
- class NOTE : public SCORE_ITEM
- {
- NOTEVAL noteval; // Value of the note
- friend istream& operator>> ( istream&, NOTE& );
- public:
- NOTE( NOTEVAL n = C, int d = 3 ) : ( d ) { noteval = n; }
- ~NOTE(){};
-
- void play();
- };
-
- class CHORD: public SCORE_ITEM
- {
- int notemask; // Notes that make up this chord
- friend istream& operator>> ( istream&, CHORD& );
- public:
- CHORD( int n = 0 , int d = 3 ) : ( d ) { notemask = n; }
- ~CHORD(){}
-
- void play();
- };
-
-
- class SEQUENCE // Class allowing sequence operations.
- {
- SCORE_ITEM* item; // Points to item
- SCORE_ITEM* last; // Points to last item
- SEQUENCE& append( SCORE_ITEM *si )
- { if ( item == (SCORE_ITEM *)NULL ) item = last = si;
- last->next = si; last = si; si->next = (SCORE_ITEM *)NULL;
- return *this; }
- friend class SEQ_ITER;
- public:
- SEQUENCE(){ item = last = (SCORE_ITEM *)NULL; };
- SEQUENCE( SCORE_ITEM& si ) { item = last = &si; }
- ~SEQUENCE(){}
- SEQUENCE& operator= ( SCORE_ITEM& si ) { item = last = &si; return *this; }
- SEQUENCE& operator= ( SEQUENCE& s2 )
- { item = s2.item; last = s2.last; return *this; }
- SEQUENCE& operator+ ( SCORE_ITEM& si ) { return append( &si ); }
- SEQUENCE& operator+= ( SCORE_ITEM& si ) { return append( &si ); }
- SEQUENCE& operator+= ( SCORE_ITEM* si ) { return append( si ); }
- };
-
-
-
- class SEQ_ITER // To follow a sequence with
- {
- SEQUENCE* seq; // Ptr to song header
- SCORE_ITEM* si; // Ptr to current item
- public:
- SEQ_ITER( SEQUENCE& sq ){ seq = &sq; si = sq.item; }
- ~SEQ_ITER(){}
- SCORE_ITEM* operator()(); // Retrieve next one
- };
-
-
-
- ----------------------------------------------------------------------
-
- /* score_c.c++ - Support functions for classes related to the "score" program
- written for the Byte C++ Review
-
- May 1987 Mark E. Mallett
-
- */
- #include <stream.h>
- #include <string.h>
- #include "score_c.h"
-
-
- /* Table of correlations between note names and noteval mnemonics */
- static struct { NOTEVAL nval; char* nname; } Nvtbl[13] = {
- { C, "C" },
- { Csh, "Csh" },
- { D, "D" },
- { Dsh, "Dsh" },
- { E, "E" },
- { F, "F" },
- { Fsh, "Fsh" },
- { G, "G" },
- { Gsh, "Gsh" },
- { A, "A" },
- { Ash, "Ash" },
- { B, "B" },
- { 0, "BAD" } };
-
-
- void SCORE_ITEM :: play() // play for generic score_items
- {
- cout << "generic item: duration=" << dec(duration,3) << "\n";
- }
-
-
- void REST :: play()
- {
- cout << "rest: duration=" << dec(dur(),3) << "\n";
- }
-
-
- void NOTE :: play()
- {
- int i;
-
- for( i = 0; i < 12; ++i )
- if ( noteval == Nvtbl[i].nval )
- break;
- cout << "note: duration=" << dec(dur(),3)
- << " value: " << Nvtbl[i].nname << "\n";
- }
-
-
- void CHORD :: play()
- {
- int i;
- int nval;
-
- cout << "chord: duration=" << dec(dur(),3) << " value:";
- for( nval = 0; nval < 12; ++nval )
- if ( notemask & (1 << nval ) )
- {
- for( i = 0; i < 12; ++i )
- if ( nval == Nvtbl[i].nval )
- break;
- cout << " " << Nvtbl[i].nname;
- }
-
- cout << "\n";
- }
-
-
-
- SCORE_ITEM* SEQ_ITER :: operator()()
- {
- SCORE_ITEM* tsi = si; // Copy of current ptr
- if ( si != (SCORE_ITEM *)NULL ) si = si -> next;
- return tsi;
- }
-
-
- istream& operator>> ( istream& s, NOTEVAL& n )
- {
- int i;
- char namebuf[100];
-
- s >> (char *)&namebuf[0]; // Input name
- for( i = 0; i < 12; ++i )
- if ( stricmp( namebuf, Nvtbl[i].nname ) == 0 )
- break;
- if ( i < 12 )
- n = Nvtbl[i].nval;
- else
- cout << "Error: '" << namebuf << "' is not a note name\n";
- return s;
- }
-
-
- istream& operator>> ( istream& s, SCORE_ITEM& si )
- {
- s >> si.duration;
- return s;
- }
-
-
- istream& operator>> ( istream& s, NOTE& n )
- {
- s >> (SCORE_ITEM& ) n;
- s >> n.noteval;
- return s;
- }
-
-
- istream& operator>> ( istream& s, CHORD& c )
- {
- NOTEVAL nval;
- char ch;
-
- s >> (SCORE_ITEM& ) c;
- c.notemask = 0; // No notes
- for( ; ; ) // Input notenames until no comma
-
- {
- s >> (NOTEVAL &) nval; // Get next note
- c.notemask |= (1 << nval);
- s >> ch; // Look for semi
- if ( ch == ';' ) // Quit when found
- break;
- s.putback( ch ); // Re-use the not-semi
- }
- return s;
- }
-
-
- ----------------------------------------------------------------------
-
- /* score.c++ - Test program for the "score" classes,
- written for the Byte C++ Review
-
- May 1987 Mark E. Mallett
-
- */
-
- #include <stream.h>
- #include <ctype.h>
-
- #include "score_c.h"
- void play( SEQUENCE& );
-
-
- main()
- {
- SEQUENCE song1;
- NOTE c1(5), c2(10);
-
- c1 = C;
- c2 = G;
- song1 = c1;
- song1 = song1 + c2 + NOTE(Dsh, 7);
- song1 += NOTE(Ash);
- play( song1 );
- cout << "\n\n";
-
-
- SEQUENCE song2;
- char c;
- cout << "Enter each element of the song in the following formats\n\n";
- cout << "r dd to enter a rest\n";
- cout << "n dd note-name to enter a note\n";
- cout << "c dd note-name... ; to enter a chord\n";
- cout << "p to play the song\n";
- cout << "x to finish\n";
-
- for( ; ; ) // Loop until done
- {
- cout << "\n> "; // Issue prompt
- cin >> c; // Get key character
- if ( isupper( c ) )
- c = tolower( c );
- if ( c == 'x' )
- break;
-
- switch ( c ) // Process input
- {
- case 'r': // rest
- REST* rest = new REST;
- cin >> *rest;
- song2 += rest;
- cout << "rest entered\n";
- break;
-
- case 'n': // note
- NOTE* note = new NOTE;
- cin >> *note;
- song2 += note;
- cout << "note entered\n";
- break;
-
- case 'c': // chord
- CHORD* chord = new CHORD;
- cin >> *chord;
- song2 += chord;
- cout << "chord entered\n";
- break;
-
- case 'p': // Play
- play( song2 ); // Play it
- break;
-
- default: // Invalid
- cout << "'" << chr(c) << "' isn't valid.\n";
- break;
- }
- }
- }
-
-
- void play( SEQUENCE &song ) // Routine to play a song
- {
- SEQ_ITER next_seq(song); // Get an iterator for the song
- SCORE_ITEM *siptr;
- while ( ( siptr = next_seq() ) != (SCORE_ITEM *)NULL )
- siptr->play();
- }
-
- *** end Score ***